package chen.you.comm.log

import java.io.File

/**
 * author: you : 2018/12/14
 * 注意此类不能混淆
 *
 */
class LogAppender(_logfileDir: String, _bufferSize: Long, _flushDelay: Long, _maxLogSize: Long, _logAliveTime: Long, isDebug: Boolean) {

    private var mNativeContext: Long? = null

    init {
        val bufferSize = fixSize(_bufferSize, MAX_BUFFERSIZE, MIN_BUFFERSIZE)
        val flushDelay = fixSize(_flushDelay, MAX_FLUSH_DELAY, MIN_FLUSH_DELAY)
        var maxLogSize = _maxLogSize
        if (maxLogSize != 0L) {
            maxLogSize = fixSize(maxLogSize, MAX_LOG_FILESIZE, MIN_LOG_FILESIZE)
            if (maxLogSize < bufferSize) { //限制最大文件不能小于缓冲大小
                maxLogSize = bufferSize
            }
        }
        val logAliveTime = fixSize(_logAliveTime, MAX_LOG_ALIVE_TIME, MIN_LOG_ALIVE_TIME)
        val logfileDir = if (_logfileDir.endsWith(File.separator)) _logfileDir else "$_logfileDir${File.separator}"
        mNativeContext = initNative(logfileDir, bufferSize, flushDelay, maxLogSize, logAliveTime, isDebug)
    }

    fun openBuffer(bufferPath: String) {
        mNativeContext?.also { openBuffer(it, bufferPath) }
    }

    fun flush() {
        mNativeContext?.also { flush(it) }
    }

    fun appender(logData: String) {
        mNativeContext?.also { appender(it, logData) }
    }

    fun closeBuffer() {
        mNativeContext?.also { closeBuffer(it) }
    }

    @Throws(Throwable::class)
    @Override
    protected fun finalize() {
        mNativeContext?.also { release(it) }
    }

    //打开日志文件,mmap映射或者native内层
    private external fun openBuffer(logAppender: Long, bufferPath: String)

    //添加日志
    private external fun appender(logAppender: Long, logData: String)

    //flush日志,异步处理
    private external fun flush(logAppender: Long)

    //关闭mmap
    private external fun closeBuffer(logAppender: Long)

    //释放
    private external fun release(logAppender: Long)

    companion object {
        init {
            System.loadLibrary("YlogCore")
        }

        //默认自动刷新日志最大时间单位 秒
        const val MAX_FLUSH_DELAY = 60 * 60L

        //最小刷新间隔, DEBUG状态时可小一点
        const val MIN_FLUSH_DELAY = 5 * 60L

        //最大与最小BufferSize 4K整数最佳
        const val MAX_BUFFERSIZE = 1024 * 1024L
        const val MIN_BUFFERSIZE = 40 * 1024L

        //最大日志文件大小, 0时只生成在一个文件中
        const val MAX_LOG_FILESIZE = 128 * 1024 * 1024L
        const val MIN_LOG_FILESIZE = 400 * 1024L

        //文件保留时间
        const val MAX_LOG_ALIVE_TIME = 10 * 24 * 3600L
        const val MIN_LOG_ALIVE_TIME = 1 * 24 * 3600L

        fun fixSize(v: Long, max: Long, min: Long): Long {
            return if (v > max) max else if (v < min) min else v
        }

        //初始化日志相关参数
        @JvmStatic
        private external fun initNative(
            logfileDir: String,
            bufferSize: Long,
            flushDelay: Long,
            maxLogSize: Long,
            maxLogAliveTime: Long,
            isDebug: Boolean
        ): Long
    }
}